home *** CD-ROM | disk | FTP | other *** search
- /* ole.c -- object library engine */
-
- #include <stdio.h>
- #include <io.h>
- #include <stdlib.h>
- #include <string.h>
- #include "ole.h"
- #include "svc.h"
-
- typedef struct {
- unsigned char symboldictblock[DICTBLOCKSIZE]; /* symbol dictionary block */
- int freespaceidx; /* cursor to next free symbol space slot */
- BOOL isfull; /* is this symb. dict. block full ? */
- int blocknumber; /* current block number */
- } DICTBLOCK;
-
- /* The number of pages in the symbol dictionary has to be prime <= 251
- NB. The smallest apge number in MS LIB is 2, in Borland TLIB is 1
- */
- static int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
- 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
- 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
- 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
- 229, 233, 239, 241, 251 };
-
- /* symbol dictionary block */
- DICTBLOCK dictblock;
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : getlibheader
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE : gets the header of an object module library
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- void getlibheader(LIBHDR *libheader, FILE *inlibfh)
- {
- if (fgetc(inlibfh) != LIBHEADER)
- output(error, NOFILE, "Bogus library header\n");
-
- /* NB. the LIBHDR data structure has been enlarged to include more info
- than the actual lib. header contains. As a result, a few more bytes
- are read in past the actual header when we take sizeof(LIBHDR). This
- is no problem as there is plenty to read after the header anyway!
- */
-
- if (fread(libheader, sizeof(LIBHDR), 1, inlibfh) != 1)
- output(error, NOFILE, "Couldn't read library header\n");
-
- /* add in header length and checksum byte */
- libheader->pagesize += 3;
-
- /* determine if lib. include MS' libmod extension */
- /* find the first OBJ module in the lib file */
- if (fseek(inlibfh, (long) libheader->pagesize, SEEK_SET) != 0)
- output(error, NOFILE, "Seek for first object module failed\n");
- libheader->islibmodformat = findlibmod(inlibfh);
- libheader->iscasesensitive = (libheader->flags == 0x01) ? TRUE : FALSE;
-
- /* make it clear that we haven't read symbol dictionary yet */
- dictblock.blocknumber = UNDEFINED;
-
- return;
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : findmodule
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- long findmodule(char *modulename, LIBHDR *libheader, FILE *inlibfh)
- {
- char *objname;
- DICTENTRY dictentry;
- char *extp;
-
- /* allow extra space for terminating "1!\0" */
- if ((objname = (char *) malloc(strlen(modulename) + 2)) == NULL)
- output(error, NOFILE, "OBJ name memory allocation failed\n");
- strcpy(objname, modulename);
-
- /* allow search for module name xxx.obj */
- if ((extp = strrchr(objname, '.')) != NULL)
- *extp = '\0';
- /* NB. module names are stored in libraries terminated by '!' */
- strcat(objname, "!");
- dictentry = findsymbol(objname, libheader, inlibfh);
-
- free(objname);
- return (dictentry.isfound == TRUE) ? dictentry.modulefilepos : -1L;
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : findsymbol
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- DICTENTRY findsymbol(char *symbolz, LIBHDR *libheader, FILE *inlibfh)
- {
- DICTENTRY dictentry;
- char *symbolp;
- hasht hashval;
- int maxtries;
- int block, bucket;
-
- hashval = hash(symbolz, libheader->numdictblocks);
- block = hashval.blockhash;
- bucket = hashval.buckethash;
- maxtries = libheader->numdictblocks * NUMBUCKETS;
- dictentry.isfound = FALSE;
-
- while (maxtries--)
- {
- dictentry = getsymdictentry(block, bucket, libheader, inlibfh);
-
- /* Three alternatives to check after the symbol dictionary lookup : */
-
- /* 1. if the entry is zero, but the dictionary block is NOT full,
- the symbol is not present
- */
- if ((dictentry.isfound == FALSE) && (dictblock.isfull == FALSE))
- return dictentry;
-
- /* 2. if the entry is zero, and the dictionary block is full, the
- symbol may have been rehashed to another bloc - keep looking
-
- 3. if the entry is non-zero, we still have to verify the symbol.
- if it is the wrong one (hash clash), keep looking
- */
- if (dictentry.isfound == TRUE)
- {
- /* get the symbol name */
- symbolp = makeasciiz(dictentry.symbolp);
-
- /* choose case-sensitive or insensitive comparison as appropriate */
- if ((libheader->iscasesensitive == TRUE) ? strcmp(symbolz, symbolp) : stricmp(symbolz, symbolp) == STR_EQUAL)
- {
- free(symbolp);
- return dictentry;
- }
-
- free(symbolp);
- }
-
- /* cases 2 & 3 (without a symbol match) require a rehash */
- block += hashval.blockovfl;
- bucket += hashval.bucketovfl;
- block %= libheader->numdictblocks;
- bucket %= NUMBUCKETS;
- }
-
- /* we never found the entry */
- dictentry.isfound = FALSE;
- return (dictentry);
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : hash
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- hasht hash(char symbolz[], int numhashblocks)
- {
- hasht symhash; /* the resulting aggregate hash values */
- unsigned char *symbolc; /* symbol with prepended count */
- int symlength; /* length of symbol to be hashed */
- unsigned char *fwdp, *bwdp; /* temp ptrs to string : forward/backward */
- unsigned int fwdc, bwdc; /* current chars at fwd/backwd pointers */
- unsigned int blockh, blockd, bucketh,
- bucketd; /* temporary values */
- int i;
-
- symlength = strlen(symbolz);
-
- /* make symbol string in length byte/ASCII string format */
- if ((symbolc = malloc(symlength + 2)) == NULL)
- output(error, NOFILE, "Memory allocation failed\n");
- symbolc[0] = (unsigned char) symlength;
-
- /* copy without EOS */
- strncpy((signed char *) &symbolc[1], symbolz, symlength + 1);
- fwdp = &symbolc[0];
- bwdp = &symbolc[symlength];
- blockh = blockd = bucketh = bucketd = 0;
-
- for (i = 0; i < symlength; i++)
- {
- /* hashing is done case-insensitive, including the length byte */
- fwdc = (unsigned int) *fwdp++ | 0x20;;
- bwdc = (unsigned int) *bwdp++ | 0x20;
-
- /* XOR the current character (moving forward or reverse, depending on
- the variable calculated) with the intermediate result rotated by
- 2 bits (again, left or right depending on variable)
- */
- /* block hash : traverse forward, rotate left */
- blockh = fwdc ^ ROL(blockh, 2);
- /* block overflow delta : traverse reverse, rotate left */
- blockd = bwdc ^ ROL(blockd, 2);
- /* bucket hash : traverse reverse, rotate right */
- bucketh = bwdc ^ ROR(bucketh, 2);
- /* bucket overflow delta : traverse forward, rotate right */
- bucketd = fwdc ^ ROR(bucketd, 2);
- }
-
- /* NB. results are zero-based */
- symhash.blockhash = blockh % numhashblocks;
- symhash.buckethash = bucketh % NUMBUCKETS;
-
- /* obviously, has deltas of zero would be nonsense */
- symhash.blockovfl = max(blockd % numhashblocks, 1);
- symhash.bucketovfl = max(bucketd % NUMBUCKETS, 1);
-
- free(symbolc);
- return (symhash);
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : getsymdictblock
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- void getsymdictblock(int blocknumber, LIBHDR *libheader, FILE *inlibfh)
- {
-
- /* find and read the whole symbol dictionary block */
- if (fseek(inlibfh, libheader->dictionaryoffset + (long) blocknumber * (long) DICTBLOCKSIZE, SEEK_SET) != 0)
- output(error, NOFILE, "Could not find symbol dictionary\n");
-
- if (fread(dictblock.symboldictblock, DICTBLOCKSIZE, 1, inlibfh) != 1)
- output(error, NOFILE, "Couldn't read library header\n");
-
- /* is this block all used up ? */
- dictblock.freespaceidx = dictblock.symboldictblock[NUMBUCKETS];
- dictblock.isfull = (dictblock.freespaceidx == DICTBLKFULL) ? TRUE : FALSE;
-
- /* for future reference, remember block number */
- dictblock.blocknumber = blocknumber;
-
- return;
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : getsymdictentry
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- DICTENTRY getsymdictentry(int blocknumber, int bucketnumber, LIBHDR *libheader, FILE *inlibfh)
- {
- DICTENTRY dictentry;
- unsigned char symboloffset;
- unsigned char symbollength;
- int pagenumber;
-
- /* remember entry's block/bucket, and initialise to no (NULL) entry */
- dictentry.blocknumber = blocknumber;
- dictentry.bucketnumber = bucketnumber;
- dictentry.symbolp = NULL;
- dictentry.isfound = FALSE;
-
- /* make sure the appropriate block was already read from .obj mod. library */
- if (dictblock.blocknumber != blocknumber)
- getsymdictblock(blocknumber, libheader, inlibfh);
-
- /* WORD offset of symbol in dictionary block (0 means no entry) */
- symboloffset = dictblock.symboldictblock[bucketnumber];
- if (symboloffset != 0)
- {
- /* since it is a word offsedt, need to multiply by 2 */
- dictentry.symbolp = &dictblock.symboldictblock[symboloffset * 2];
-
- /* get the symbol's object module offset in lib. */
- symbollength = *dictentry.symbolp;
-
- /* object module's lib. page number is right after symbol string */
- pagenumber = *(int *) (dictentry.symbolp + symbollength + 1);
- dictentry.modulefilepos = (long) pagenumber * (long) libheader->pagesize;
- dictentry.isfound = TRUE;
- }
-
- return dictentry;
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : getmodulename
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- char *getmodulename(long modulefilepos, LIBHDR *libheader, FILE *inlibfh)
- {
- int symbollength;
- char *modulename;
- OMFHEADER omfheader;
-
- /* position at beginning of pertinent object module */
- if (fseek(inlibfh, modulefilepos, SEEK_SET) != 0)
- output(error, NOFILE, "seek for object module at %lx failed\n", modulefilepos);
-
- if (libheader->islibmodformat == FALSE)
- {
- if (fread(&omfheader, sizeof(omfheader), 1, inlibfh) != 1)
- output(error, NOFILE, "Couldn't read THEADR at %lx\n", modulefilepos);
- if (omfheader.rectype != THEADR)
- output(error, NOFILE, "Bogus THEADR OMF record at %lx\n", modulefilepos);
- }
- else
- if (findlibmod(inlibfh) == FALSE)
- {
- output(warning, NOFILE, "No LIBMOD record found at %lx\n", modulefilepos);
- return NULL;
- }
-
- symbollength = fgetc(inlibfh);
- if ((modulename = (char *) malloc(symbollength + 1)) == NULL)
- output(error, NOFILE, "MALLOC failure reading module name\n");
- if (fread(modulename, symbollength, 1, inlibfh) != 1)
- output(error, NOFILE, "Couldn't read THREADR\n");
- modulename[symbollength] = '\0';
-
- return modulename;
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : findlibmod
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- BOOL findlibmod(FILE *inlibfh)
- {
- COMMENTHEADER commenthdr;
-
- /* search (up to) all COMENT records in OBJ module */
- while (findobjrecord(inlibfh, COMENT) == TRUE)
- {
- if (fread(&commenthdr, sizeof(commenthdr), 1, inlibfh) != 1)
- output(error, NOFILE, "Couldn't read OBJ\n");
- if (commenthdr.commentclass == LIBMOD)
- return TRUE;
- else
- /* if not found : forward to next record and retry */
- if (fseek(inlibfh, (long) commenthdr.reclength - sizeof(commenthdr) + sizeof(OMFHEADER), SEEK_SET) != 0)
- output(error, NOFILE, "Seek try for LIBMOD failed\n");
- }
-
- /* we got here only if COMENT of class LIBMOD was never found */
- return FALSE;
- }
-
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : findobjrecord
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- BOOL findobjrecord(FILE *objfh, unsigned char rectype)
- {
- OMFHEADER objheader;
-
- while (fread(&objheader, sizeof(objheader), 1, objfh) == 1)
- {
- /* if is is the record type we are looking for, we're done */
- if (objheader.rectype == rectype)
- {
- /* return with obj module set to record requested */
- if (fseek(objfh, -(long) sizeof(objheader), SEEK_CUR) != 0)
- output(error, NOFILE, "Seek for record type %02x failed\n", rectype & 0xff);
- return TRUE;
- }
-
- /* end of object module, record type NEVER found */
- if (objheader.rectype == MODEND)
- return FALSE;
-
- /* forward file pointer to next object module record */
- if (fseek(objfh, (long) objheader.reclength, SEEK_CUR) != 0)
- output(error, NOFILE, "Seek retry for record type %02x failed\n", rectype & 0xff);
- }
-
- /* if this quit due to I/O condition, its either EOF or I/O error */
- if (feof(objfh) == 0)
- output(error, NOFILE, "Couldn't read OBJ\n");
-
- /* we completed without error and without finding the record (should NEVER happen) */
- return FALSE;
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : extractmodule
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- BOOL extractmodule(char *modulename, char *newmodulename, LIBHDR *libheader, FILE *inlibfh)
- {
- long filepos;
- char *newobjp;
- char *newobjname;
- FILE *newobjfh;
-
- /* find the object module's position in the library file */
- filepos = findmodule(modulename, libheader, inlibfh);
- if (filepos == -1L)
- return FALSE;
-
- /* determine the name for the new obj, and set it up */
- newobjp = (newmodulename != NULL) ? newmodulename : modulename;
- if ((newobjname = (char *) malloc(strlen(newobjp) + 5)) == NULL)
- output(error, NOFILE, "MALLOC failure making module name\n");
- strcpy(newobjname, newobjp);
-
- /* open the new .obj file, and pass everything off to a low-level routine */
- if ((newobjfh = fopen(newobjname, "wb")) == NULL)
- output(error, NOFILE, "Failure opening new module file\n");
-
- copyobjmodule(newobjfh, filepos, inlibfh);
-
- fclose(newobjfh);
- free(newobjname);
- return TRUE;
- }
-
-
- /*----------------------------------------------------------------------------------
- FUNCTION : copyobjmodule
-
- PROGRAMMER : Glen Downton VERSION : 01 DATE : Nov 17,1991
- Originally published in Dr. Dobb's Journal (Sep. 1991)
- "OBJ Library Management" -- Thomas Siering
-
- PURPOSE :
-
- ALGORITHM :
-
- PARAMETERS :
-
- RETURNS :
-
- FUNCTION CALLS :
-
- USAGE :
- --------------------------------------------------------------------------------------*/
- void copyobjmodule(FILE *newobjfh, long filepos, FILE *inlibfh)
- {
- OMFHEADER rechdr;
-
- /* get to the object module in LIB */
- if (fseek(inlibfh, filepos, SEEK_SET) != 0)
- output(error, NOFILE, "Seek failure to file position %ld\n", filepos);
-
- /* write module from LIB to separate obj file */
- do {
- /* read OMF header record, this will give record type and length */
- if (fread(&rechdr, sizeof(rechdr), 1, inlibfh) != 1)
- output(error, NOFILE, "Couldn't read OBJ\n");
-
- /* need to check every COMENT record to make sure to strip LIBMOD out */
- if (rechdr.rectype == COMENT)
- {
- /* throw out next byte (attrib COMENT byte) for now */
- fgetc(inlibfh);
-
- /* check COMENT's comment class
- if it is a LIBMOD, set file pointer to next record and continue
- */
- if (fgetc(inlibfh) == LIBMOD)
- {
- if (fseek(inlibfh, (long) rechdr.reclength - 2L, SEEK_CUR) != 0)
- output(error, NOFILE, "Seek error on COMENT\n");
- continue;
- }
- else
- /* wasn't a LIBMOD : reset file pointer to continue normally */
- if (fseek(inlibfh, -2L, SEEK_CUR) != 0)
- output(error, NOFILE, "Seek error on COMENT\n");
- }
-
- if (fwrite(&rechdr, sizeof(rechdr), 1, newobjfh) != 1)
- output(error, NOFILE, "Couldn't write new OBJ\n");
-
- while (rechdr.reclength--)
- fputc(fgetc(inlibfh), newobjfh);
-
- } while (rechdr.rectype != MODEND);
-
- return;
- }
-
-
-
-
-
-